import dash
from dash import dcc, html
import plotly.graph_objects as go
import plotly.express as px
from dash.dependencies import Input, Output
import pandas as pd
from data_fetcher import DataFetcher
from flask import request

class DashApp:
    """
    创建Dash应用程序和图表
    """
    
    def __init__(self, port=8050):
        """
        初始化Dash应用程序
        
        Args:
            port (int): Dash应用程序运行的端口号
        """
        self.port = port
        self.app = dash.Dash(__name__, 
                           suppress_callback_exceptions=True,
                           meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}])
        
        # 设置应用程序布局
        self.app.layout = html.Div([
            html.H1("数据可视化仪表盘", style={'textAlign': 'center', 'marginBottom': 30}),
            
            # 创建2x2网格布局
            html.Div([
                # 第一行
                html.Div([
                    # 惠州气温折线图
                    html.Div([
                        html.H3("最近一个月惠州气温", style={'textAlign': 'center'}),
                        dcc.Graph(id='huizhou-temp-chart')
                    ], className='six columns', style={'width': '48%', 'display': 'inline-block'}),
                    
                    # 黄金价格趋势图
                    html.Div([
                        html.H3("最近30天黄金价格趋势", style={'textAlign': 'center'}),
                        dcc.Graph(id='gold-price-chart')
                    ], className='six columns', style={'width': '48%', 'display': 'inline-block', 'float': 'right'})
                ], className='row'),
                
                # 第二行
                html.Div([
                    # 中国气压分布图
                    html.Div([
                        html.H3("中国各地气压分布", style={'textAlign': 'center'}),
                        dcc.Graph(id='china-pressure-chart')
                    ], className='six columns', style={'width': '48%', 'display': 'inline-block'}),
                    
                    # 离岸人民币走势图
                    html.Div([
                        html.H3("离岸人民币汇率走势", style={'textAlign': 'center'}),
                        dcc.Graph(id='cny-rate-chart')
                    ], className='six columns', style={'width': '48%', 'display': 'inline-block', 'float': 'right'})
                ], className='row')
            ]),
            
            # 隐藏的刷新组件
            dcc.Interval(
                id='interval-component',
                interval=60*1000,  # 每分钟刷新一次 (60000毫秒)
                n_intervals=0
            )
        ], style={'padding': '20px'})
        
        # 设置回调函数
        self._setup_callbacks()
    
    def _setup_callbacks(self):
        """
        设置Dash应用程序的回调函数
        """
        # 惠州气温折线图回调
        @self.app.callback(
            Output('huizhou-temp-chart', 'figure'),
            [Input('interval-component', 'n_intervals')]
        )
        def update_huizhou_temp_chart(_):
            df = DataFetcher.get_huizhou_temperature()
            if df.empty:
                return go.Figure().update_layout(title="无法获取惠州气温数据")
            
            fig = go.Figure()
            fig.add_trace(go.Scatter(
                x=df['date'], 
                y=df['high_temp'], 
                mode='lines+markers',
                name='最高气温',
                line=dict(color='red')
            ))
            fig.add_trace(go.Scatter(
                x=df['date'], 
                y=df['low_temp'], 
                mode='lines+markers',
                name='最低气温',
                line=dict(color='blue')
            ))
            
            fig.update_layout(
                title="惠州最近一个月气温变化",
                xaxis_title="日期",
                yaxis_title="温度 (°C)",
                legend_title="温度类型",
                hovermode="x unified"
            )
            
            return fig
        
        # 黄金价格趋势图回调
        @self.app.callback(
            Output('gold-price-chart', 'figure'),
            [Input('interval-component', 'n_intervals')]
        )
        def update_gold_price_chart(_):
            df = DataFetcher.get_gold_price()
            if df.empty:
                return go.Figure().update_layout(title="无法获取黄金价格数据")
            
            fig = go.Figure()
            fig.add_trace(go.Scatter(
                x=df['date'], 
                y=df['price'], 
                mode='lines',
                fill='tozeroy',
                line=dict(color='gold')
            ))
            
            fig.update_layout(
                title="最近30天黄金价格趋势",
                xaxis_title="日期",
                yaxis_title="价格 (美元/盎司)",
                hovermode="x unified"
            )
            
            return fig
        
        # 中国气压分布图回调
        @self.app.callback(
            Output('china-pressure-chart', 'figure'),
            [Input('interval-component', 'n_intervals')]
        )
        def update_china_pressure_chart(_):
            df = DataFetcher.get_china_pressure()
            if df.empty:
                return go.Figure().update_layout(title="无法获取中国气压分布数据")
            
            # 使用普通散点图而不是地图
            fig = px.scatter(
                df, 
                x="lon", 
                y="lat", 
                color="pressure",
                size="pressure",
                size_max=15,
                hover_name="city",
                hover_data=["pressure"],
                color_continuous_scale=px.colors.sequential.Plasma,
                title="中国各地气压分布"
            )
            
            # 添加中国主要城市名称
            for i, row in df.iterrows():
                fig.add_annotation(
                    x=row['lon'],
                    y=row['lat'],
                    text=row['city'],
                    showarrow=False,
                    font=dict(size=8),
                    xshift=0,
                    yshift=10
                )
            
            # 设置坐标轴范围以覆盖中国区域
            fig.update_layout(
                xaxis=dict(
                    title="经度",
                    range=[70, 140],
                    showgrid=True
                ),
                yaxis=dict(
                    title="纬度",
                    range=[15, 55],
                    showgrid=True
                ),
                height=500,
                margin={"r":20,"t":50,"l":20,"b":20}
            )
            
            return fig
        
        # 离岸人民币走势图回调
        @self.app.callback(
            Output('cny-rate-chart', 'figure'),
            [Input('interval-component', 'n_intervals')]
        )
        def update_cny_rate_chart(_):
            df = DataFetcher.get_cny_exchange_rate()
            if df.empty:
                return go.Figure().update_layout(title="无法获取离岸人民币汇率数据")
            
            fig = go.Figure()
            fig.add_trace(go.Scatter(
                x=df['date'], 
                y=df['rate'], 
                mode='lines',
                line=dict(color='green', width=2)
            ))
            
            # 添加移动平均线
            df['ma5'] = df['rate'].rolling(window=5).mean()
            fig.add_trace(go.Scatter(
                x=df['date'], 
                y=df['ma5'], 
                mode='lines',
                name='5日移动平均线',
                line=dict(color='orange', width=1, dash='dash')
            ))
            
            fig.update_layout(
                title="离岸人民币汇率走势 (USD/CNY)",
                xaxis_title="日期",
                yaxis_title="汇率 (USD/CNY)",
                hovermode="x unified"
            )
            
            return fig
    
    def run(self, debug=False):
        """
        运行Dash应用程序(适合嵌入式使用)
        
        Args:
            debug (bool): 是否启用调试模式
        """
        self.app.run(
            debug=debug,
            port=self.port,
            host='127.0.0.1',
            use_reloader=False,
            dev_tools_hot_reload=False,
            dev_tools_ui=False
        )
    
    def get_app(self):
        """
        获取Dash应用程序实例
        
        Returns:
            dash.Dash: Dash应用程序实例
        """
        return self.app
